package com.koron.tool.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.koron.bean.base.Response;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.bean.util.DefaultIdGenerator;
import com.koron.bean.workflow.RedirectQuery;
import com.koron.common.core.business.workflow.bean.properties.WorkflowProperties;
import com.koron.common.core.business.workflow.templates.WorkFlowHandler;
import com.koron.tool.bean.*;
import com.koron.tool.enums.WarningReasonEnum;
import com.koron.tool.fegin.SystemFeignService;
import com.koron.tool.mapper.DictDataMapper;
import com.koron.tool.mapper.ToolAccountsManagerMapper;
import com.koron.tool.mapper.ToolInspectionManagerMapper;
import com.koron.tool.mapper.ToolWarningInfoMapper;
import com.koron.tool.service.ToolInspectionManagerService;
import com.koron.tool.util.BeanUtil;
import com.koron.tool.util.PdfUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: liaodf
 * @Date: 2021/10/25 17:33
 */
@Slf4j
@Service
public class ToolInspectionManagerServiceImpl implements ToolInspectionManagerService {

    @Autowired
    private WorkFlowHandler workFlowHandler;

    @Autowired
    private SystemFeignService systemFeignService;

    @Override
    @TaskAnnotation("getInspectionTools")
    public Response getInspectionTools(SessionFactory factory, ToolQuery query) {
        try {
            ToolInspectionManagerMapper mapper = factory.getMapper(ToolInspectionManagerMapper.class);
            // 获取所有符合条件的工具
            PageHelper.startPage(query.getPage(), query.getPageSize());
            List<ToolInspectionDetailBean> list = mapper.getInspectionTools(query);
            list.forEach(bean->{
                if (StringUtils.isBlank(bean.getInspectionResult())){
                    bean.setInspectionResult("合格");
                }
            });
            PageInfo pageInfo = new PageInfo(list);
            return Response.ok(pageInfo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("getInspectionList")
    public Response getInspectionList(SessionFactory factory, ToolInspectionQuery query) {
        try {
            ToolInspectionManagerMapper mapper = factory.getMapper(ToolInspectionManagerMapper.class);
            PageHelper.startPage(query.getPage(), query.getPageSize());
            List<ToolInspectionBean> list = mapper.getInspectionList(query);
            PageInfo pageInfo = new PageInfo(list);
            return Response.ok(pageInfo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("getInspection")
    public Response getInspection(SessionFactory factory, EamUser user, String id) {
        try {
            if (StringUtils.isEmpty(id)) {
                return Response.fail("参数id不能为空");
            }
            ToolInspectionManagerMapper mapper = factory.getMapper(ToolInspectionManagerMapper.class);
            ToolInspectionBean inspection = mapper.getInspection(id);
            if (null == inspection) {
                return Response.fail("检验单不存在");
            }
            List<ToolInspectionDetailBean> inspectionDetailList = mapper.getInspectionDetailList(id);
            inspectionDetailList.forEach(bean->{
                if (StringUtils.isBlank(bean.getInspectionResult())){
                    bean.setInspectionResult("合格");
                }
            });
            inspection.setToolInspectionDetailList(inspectionDetailList);
            return Response.ok(inspection);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail("执行失败");
        }
    }

    @Override
    @TaskAnnotation("savaInspection")
    public Response savaInspection(SessionFactory factory, EamUser user, ToolInspectionBean bean, Integer operation) {
        try {
            if (StringUtils.isEmpty(bean.getTitle())) {
                return Response.fail("标题不能为空");
            }
            if (StringUtils.isEmpty(bean.getBelongsUnitId()) || StringUtils.isEmpty(bean.getBelongsUnit())) {
                return Response.fail("工器具管理单位不能为空");
            }
            if (StringUtils.isEmpty(bean.getVoucherPeople())) {
                return Response.fail("制单人不能为空");
            }
            if (operation == 0) {
                bean.setInspectionStatus("draft");
            } else {
                bean.setInspectionStatus("review");
            }
            String orderNo = DefaultIdGenerator.getInstance().generateLongId();
            bean.setOrderNo(orderNo);
            ToolInspectionManagerMapper mapper = factory.getMapper(ToolInspectionManagerMapper.class);
            Integer value = 0;
            if (StringUtils.isEmpty(bean.getId())) {
                BeanUtil.add(user, bean);
                bean.setVoucherDate(System.currentTimeMillis() / 1000L);
                bean.setVoucherPeople(user.getName());
                value = mapper.insert(bean);
            } else {
                BeanUtil.update(user, bean);
                value = mapper.update(bean);
            }
            List<ToolInspectionDetailBean> detailBeanList = bean.getToolInspectionDetailList();
            if (value > 0 && null != detailBeanList && detailBeanList.size() > 0) {
                // 先删除历史数据，再新增
                mapper.deleteInsertDetail(bean.getId());
                for (ToolInspectionDetailBean detailBean : detailBeanList) {
                    BeanUtil.add(user, detailBean);
                    detailBean.setInspectionId(bean.getId());
                    mapper.InsertDetail(detailBean);
                }
                // 生成校验单后取消预警
                Set<String> codes = new HashSet<>();
                detailBeanList.forEach(detailBean -> {
                    codes.add(detailBean.getCode());
                });
                factory.getMapper(ToolWarningInfoMapper.class)
                        .batchUpdateStatus(WarningReasonEnum.REACH_THE_INSPECTION_PERIOD.getReason(), codes);
            }
            if (value > 0 && operation == 1) {
                // TODO 启动流程
                //启动工作流
                WorkflowProperties wfp = WorkflowProperties.init("tool_inspection_code");
                Map map = new HashMap(5);
                map.put("referPeople", bean.getReferPeople());
                workFlowHandler.start(wfp, bean.getId(), bean.getOrderNo(), bean.getTitle(), map);
                bean.setCurrentNode("call-Process-task1");
                bean.setCurrentProcessor(bean.getReferPeopleName());
                mapper.update(bean);
            }
            return Response.ok(bean);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail("执行失败");
        }
    }

    @Override
    @TaskAnnotation("updateInspection")
    public Response updateInspection(SessionFactory factory, EamUser user, ToolInspectionBean bean) {
        try {
            List<ToolInspectionDetailBean> detailBeanList = bean.getToolInspectionDetailList();
            BeanUtil.update(user, bean);
            ToolInspectionManagerMapper mapper = factory.getMapper(ToolInspectionManagerMapper.class);
            Integer value = mapper.update(bean);
            if (value > 0 && null != detailBeanList && detailBeanList.size() > 0) {
                // 先删除历史数据，再新增
                mapper.deleteInsertDetail(bean.getId());
                for (ToolInspectionDetailBean detailBean : detailBeanList) {
                    BeanUtil.add(user, detailBean);
                    detailBean.setInspectionId(bean.getId());
                    mapper.InsertDetail(detailBean);
                }
            }
            return Response.ok(value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail("执行失败");
        }
    }

    @Override
    @TaskAnnotation("updateState")
    public Response updateState(SessionFactory factory, RedirectQuery redirectQuery) {
        try {
            // 获取业务id
            String dataId = redirectQuery.getDataId();
            ToolInspectionManagerMapper mapper = factory.getMapper(ToolInspectionManagerMapper.class);
            ToolInspectionBean inspection = mapper.getInspection(dataId);
            // 流程结束，更新状态为归档
            if ("END".equals(redirectQuery.getCurNodeCode())) {
                inspection.setCurrentNode(redirectQuery.getCurNodeName());
                inspection.setCurrentProcessor(redirectQuery.getRelatedUser());
                inspection.setInspectionStatus("archive");
                //获取明细工具
                List<ToolInspectionDetailBean> detailList = mapper.getInspectionDetailList(dataId);
                // 获取工具编码
                List<String> toolCodes = detailList.stream().map(bean -> bean.getCode()).collect(Collectors.toList());
                // 获取检验不合格的编码
                List<String> unqualifiedCode = detailList.stream().filter(bean -> ("不合格").equals(bean.getInspectionResult())).map(bean -> bean.getCode()).collect(Collectors.toList());
                Map map = new HashMap();
                map.put("id", dataId);
                map.put("toolCodes", toolCodes);
                long newInspectionDate = inspection.getNewInspectionDate() != null ? inspection.getNewInspectionDate() : System.currentTimeMillis() / 1000L;
                inspection.setNewInspectionDate(newInspectionDate);
                map.put("newInspectionDate", newInspectionDate);
                map.put("nextInspectionDate", inspection.getNextInspectionDate());
                // 修改检验单明细本次检验时间和下次检验时间
                mapper.updateDetail(map);
                // 修改工具本次检验时间和下次检验时间
                mapper.updateTool(map);
                if (null != unqualifiedCode && unqualifiedCode.size() > 0) {
                    // 更新工具报废原因为检验不合格
                    Map map1 = new HashMap();
                    map1.put("unqualifiedCode",unqualifiedCode);
                    mapper.updateToolScrapWhy(map1);
                }
            } else if ("CANCEL".equals(redirectQuery.getCurNodeCode())) {
                // 流程废弃，更新状态为草稿
                inspection.setCurrentNode("");
                inspection.setCurrentProcessor("");
                inspection.setInspectionStatus("draft");
            } else {
                // 流程通过，更新状态为草稿
                inspection.setCurrentNode(redirectQuery.getCurNodeName());
                inspection.setCurrentProcessor(redirectQuery.getRelatedUser());
                if ("call-Process-task1".equals(redirectQuery.getCurNodeCode())) {
                    // 派发节点设置为审核中
                    inspection.setInspectionStatus("review");
                } else if ("call-Process-task2".equals(redirectQuery.getCurNodeCode())) {
                    // 检验节点设置为校验中
                    inspection.setInspectionStatus("testing");
                    JSONObject object = JSONObject.parseObject(redirectQuery.getFormVariables());
                    String inspectionPeople = object.get("inspectionPeople").toString();
                    inspection.setInspectionPeople(inspectionPeople);
                    // 根据账号获取人员信息
                    // RPC 方式
                    EamUser eamUser = systemFeignService.queryStaffInfo(inspectionPeople).getData();
                    inspection.setInspectionPeopleName(eamUser.getName());
                    // fix-bug: 检验中状态的单据的当前处理人未更新
                    if (StringUtils.isEmpty(inspection.getCurrentProcessor())) {
                        inspection.setCurrentProcessor(eamUser.getName());
                    }
                }
            }
            mapper.update(inspection);
            return Response.ok();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("exportPdf")
    public void exportPdf(SessionFactory factory, EamUser user, String id, OutputStream outputStream) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            ToolInspectionManagerMapper mapper = factory.getMapper(ToolInspectionManagerMapper.class);
            ToolAccountsManagerMapper toolMapper = factory.getMapper(ToolAccountsManagerMapper.class);
            // 获取检验单
            ToolInspectionBean inspection = mapper.getInspection(id);
            if (null == inspection) {
                return;
            }
            // 获取检验单详情
            List<ToolInspectionDetailBean> detailList = mapper.getInspectionDetailList(id);
            // 创建Document
            Document document = new Document();
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);
            writer.setViewerPreferences(PdfWriter.PageModeUseThumbs);
            // 设置页面大小
            document.setPageSize(PageSize.A4);
            document.open();
            // 创建一个PDF表单
            PdfPTable table = PdfUtil.createTable(8);
            // 设置字体
            // 标题
            Font headFont = PdfUtil.getFont(14, Font.NORMAL);
            // 表头
            Font tableFont = PdfUtil.getFont(12, Font.NORMAL);
            // 内容
            Font textFont = PdfUtil.getFont(10, Font.NORMAL);

            table.addCell(PdfUtil.createCell("标题", tableFont, Element.ALIGN_LEFT, 1, 0));
            table.addCell(PdfUtil.createCell(inspection.getTitle(), tableFont, Element.ALIGN_LEFT, 7, 0));
            table.addCell(PdfUtil.createCell("单据信息", headFont, Element.ALIGN_LEFT, 8, 0));
            table.addCell(PdfUtil.createCell("检验内容", tableFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell(inspection.getContent(), textFont, Element.ALIGN_CENTER, 6, 0));
            table.addCell(PdfUtil.createCell("工器具管理单位", tableFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell(inspection.getBelongsUnit(), textFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell("制单人", tableFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell(inspection.getVoucherPeople(), textFont, Element.ALIGN_CENTER, 2, 0));
            //table.addCell(PdfUtil.createCell("", tableFont, Element.ALIGN_CENTER, 2, 0));
            //table.addCell(PdfUtil.createCell("", textFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell("检验信息", headFont, Element.ALIGN_LEFT, 8, 0));
            //table.addCell(PdfUtil.createCell("检验工具清单", tableFont, Element.ALIGN_CENTER, 8, 0));
            table.addCell(PdfUtil.createCell("名称", tableFont, Element.ALIGN_CENTER, 0, 0));
            table.addCell(PdfUtil.createCell("所属单位", tableFont, Element.ALIGN_CENTER, 0, 0));
            table.addCell(PdfUtil.createCell("所属库房", tableFont, Element.ALIGN_CENTER, 0, 0));
            table.addCell(PdfUtil.createCell("工器具类型", tableFont, Element.ALIGN_CENTER, 0, 0));
            table.addCell(PdfUtil.createCell("下次体验日期", tableFont, Element.ALIGN_CENTER, 0, 0));
            table.addCell(PdfUtil.createCell("库存状态", tableFont, Element.ALIGN_CENTER, 0, 0));
            table.addCell(PdfUtil.createCell("检验结果", tableFont, Element.ALIGN_CENTER, 0, 0));
            table.addCell(PdfUtil.createCell("备注", tableFont, Element.ALIGN_CENTER, 0, 0));
            if (null != detailList && detailList.size() > 0) {
                for (ToolInspectionDetailBean detailBean : detailList) {
                    table.addCell(PdfUtil.createCell(detailBean.getName(), textFont, Element.ALIGN_CENTER, 0, 0));
                    table.addCell(PdfUtil.createCell(detailBean.getBelongsUnit(), textFont, Element.ALIGN_CENTER, 0, 0));
                    table.addCell(PdfUtil.createCell(detailBean.getWarehouse(), textFont, Element.ALIGN_CENTER, 0, 0));
                    //所属类型
                    ToolGroupBean getToolGroupByCode = toolMapper.getToolGroupByCode(detailBean.getToolTyleCode());
                    table.addCell(PdfUtil.createCell(getToolGroupByCode.getName(), textFont, Element.ALIGN_CENTER, 0, 0));

                    table.addCell(PdfUtil.createCell(null == detailBean.getNextInspectionDate() ? "" : sdf.format(new Date(detailBean.getNextInspectionDate() * 1000L)), textFont, Element.ALIGN_CENTER, 0, 0));
                    Map map = new HashMap();
                    map.put("inventoryStatus", "inventoryStatus");
                    map.put("itemCode", detailBean.getInventoryStatus());
                    String itemName = factory.getMapper(DictDataMapper.class).getDictItem(map);
                    table.addCell(PdfUtil.createCell(itemName, textFont, Element.ALIGN_CENTER, 0, 0));
                    table.addCell(PdfUtil.createCell(detailBean.getInspectionResult(), textFont, Element.ALIGN_CENTER, 0, 0));
                    table.addCell(PdfUtil.createCell(detailBean.getRemarks(), textFont, Element.ALIGN_CENTER, 0, 0));
                }
            }
            table.addCell(PdfUtil.createCell("工具检验信息更新", tableFont, Element.ALIGN_CENTER, 8, 0));
            table.addCell(PdfUtil.createCell("检验人员", tableFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell(inspection.getInspectionPeopleName(), textFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell("检验单位", tableFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell(inspection.getInspectionUnit(), textFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell("本次检验日期", tableFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell(inspection.getNewInspectionDate() == null ? "" : sdf.format(new Date(inspection.getNewInspectionDate() * 1000L)), textFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell("下次检验日期", tableFont, Element.ALIGN_CENTER, 2, 0));
            table.addCell(PdfUtil.createCell(null == inspection.getNextInspectionDate() ? "" : sdf.format(new Date(inspection.getNextInspectionDate() * 1000L)), textFont, Element.ALIGN_CENTER, 2, 0));
            document.add(table);
            document.close();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return;
        }
    }

    @Override
    @TaskAnnotation("exportInspectionQualification")
    public void exportInspectionQualification(SessionFactory sessionFactory, EamUser user, String id, OutputStream os) {
        try {
            ToolInspectionManagerMapper mapper = sessionFactory.getMapper(ToolInspectionManagerMapper.class);
            ToolInspectionBean inspectionBean = mapper.getInspection(id);
            if (inspectionBean == null) {
                return;
            }
            List<ToolInspectionDetailBean> inspectionDetailList = mapper.getInspectionDetailList(id);
            inspectionDetailList = inspectionDetailList.stream().filter(bean -> "合格".equals(bean.getInspectionResult())).collect(Collectors.toList());

            // 创建Document
            Document document = new Document();
            PdfWriter writer = PdfWriter.getInstance(document, os);
            // 打开document
            document.open();
            // 创建外层table，分成两列
            PdfPTable outerTable = PdfUtil.createTable(2);
            // 表头字体格式
            Font headFont = PdfUtil.getFont(14, Font.NORMAL);
            // 内容字体格式
            Font contentFont = PdfUtil.getFont(10, Font.NORMAL);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
            inspectionDetailList.forEach(bean -> {
                PdfPTable innerTable = new PdfPTable(2);
                innerTable.addCell(PdfUtil.createCell("安全工器具检验合格证", headFont, Element.ALIGN_CENTER, 2, 0));
                innerTable.addCell(PdfUtil.createCell("名称", headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell(bean.getName(), headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell("编号", headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell(bean.getToolNumber(), headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell("货架名称", headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell(bean.getToolTyle()  , headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell("本次检验日期", headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell(sdf.format(bean.getNewInspectionDate() * 1000), headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell("下次检验日期", headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell(sdf.format(bean.getNextInspectionDate() * 1000), headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell("检验人员", headFont, Element.ALIGN_CENTER, 1, 0));
                innerTable.addCell(PdfUtil.createCell(inspectionBean.getInspectionPeopleName(), headFont, Element.ALIGN_CENTER, 1, 0));
                PdfPCell cell = new PdfPCell();
                cell.setBorderWidth(0f);
                cell.setPaddingBottom(40f);
                cell.setPaddingRight(10f);
                cell.addElement(innerTable);
                outerTable.addCell(cell);
            });
            // 添加空白cell，避免异常
            if (inspectionDetailList.size() % 2 != 0) {
                PdfPCell pdfPCell = new PdfPCell();
                pdfPCell.setBorderWidth(0f);
                outerTable.addCell(pdfPCell);
            }
            if (CollectionUtils.isEmpty(inspectionDetailList)) {
                document.add(new Paragraph("此检验单中无合格工器具。", headFont));
            }
            document.add(outerTable);
            document.close();
            writer.close();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

}
